<html>
<head>
<title>IYOCGwP Book 1 - Chapter 9 - Sonar</title>
<link rel="stylesheet" href="inventbook.css" type="text/css" media="all">
</head>
<body>

<h1>Chapter 9 - Sonar</h1>

<p>Sonar is a technique that ships use to locate objects under the sea. In this chapter's game, the player places sonar devices at various places in the ocean to locate sunken treasure chests. The sonar devices in our game can only tell the player how far away a treasure chest is from the sonar device, but not in what direction. But by placing multiple sonar devices down, the player can figure out where exactly the treasure chest is. There are three chests to collect, but the player has only sixteen sonar devices to use to find them.</p>

<p>Imagine that we could not see the treasure chest (the red dot) in the following picture. Because each sonar device can only find the distance but not direction, the possible places the treasure could be is anywhere in a ring around the sonar device:</p>

<p class='centeredImageP'><img src='images/9_sonar1.png' class='centeredImage'></p>

<p>But if we have multiple sonar devices combined together, we can narrow it down to one exact place where all the rings intersect each other:</p>

<p class='centeredImageP'><img src='images/9_sonar2.png' class='centeredImage'></p>

<h2>Grids and Cartesian Coordinates</h2>

<p>A common problem in many games is how to talk about exact points in some area. A common way of solving this is by marking each individual row and column on a board with letters and numbers. Here is a chess board that has each row marked with numbers, and each column marked with letters.</p>

<p class='centeredImageP'><img src='images/9_chess1.png' class='centeredImage'></p>

<p>In chess, the knight piece looks like a horse head. We can say that the white knight is located at the point e, 6. The black knight is located at point a, 4. We can also say that every space on row 7 or every space in column c is empty.</p>

<p>A grid with labeled rows and columns like this is called a <span class='term'>Cartesian coordinate system</span>. By using a row label and column label, we can give a coordinate that points to exactly one and only one space. This can really help us describe to a computer an exact location. If you have learned about Cartesian coordinate systems in math class, you may know that usually we have numbers for both the rows and columns. This is handy, because otherwise after the 26th column we would run out of letters. That board would look like this:</p>

<p class='centeredImageP'><img src='images/9_chess2.png' class='centeredImage'></p>

<p>The numbers going left and right that describe the columns are part of the <span class='term'>X-axis</span>. The numbers going up and down that describe the rows are part of the <span class='term'>Y-axis</span>. When we describe coordinates, we always say the X coordinate first, followed by the Y coordinate. That means the white knight in the above picture is located at the coordinate 5, 6. The black knight is located at the coordinate 1, 4.</p>

<p>Notice that for the black knight to move to the white knight's position, the black knight must move up two spaces, and then to the right by four spaces. (Or move right four spaces and then move up two spaces.) But we don't need to look at the board to figure this out. If we know the white knight is located at 5, 6 and the black knight is located at 1, 4, then we can just use subtraction to figure out this information.</p>

<p>Subtract the black knight's X coordinate and white knight's X coordinate: 5 - 1 = 4. That means the black knight has to move along the X-axis by four spaces.</p>

<p>Subtract the black knight's Y coordinate and white knight's Y coordinate: 6 - 4 = 2. That means the black knight has to move along the Y-axis by two spaces.</p>

<h2>Negative Numbers</h2>

<p>Another concept that Cartesian coordinates use is negative numbers. <span class='term'>Negative numbers</span> are numbers that are smaller than zero. We put a minus sign in front of a number to show that it is a negative number. -1 is smaller than 0. -2 is smaller than -1. -3 is smaller than -2. If you think of regular numbers (called <span class='term'>positive numbers</span>) as starting from 1 and increasing, you can think of negative numbers as starting from -1 and decreasing. 0 itself is not positive or negative. In this picture, you can see the positive numbers increasing to the right and the negative numbers decreasing to the left:</p>

<p class='centeredImageP'><img src='images/9_numberline.png' class='centeredImage'></p>

<p>The number line is really useful for doing subtraction and addition with negative numbers. The expression 4 + 3 can be thought of as the white knight starting at position 4 and moving 3 spaces over to the right (addition means increasing, which is in the right direction).</p>

<p class='centeredImageP'><img src='images/9_numberline2.png' class='centeredImage'></p>

<p>As you can see, the white knight ends up at position 7. This makes sense, because 4 + 3 is 7.</p>

<p>Subtraction can be done by moving the white knight to the left. Subtraction means decreasing, which is in the left direction. 4 - 6 would be the white knight starting at position 4 and moving 6 spaces to the left:</p>

<p class='centeredImageP'><img src='images/9_numberline3.png' class='centeredImage'></p>

<p>The white knight ends up at position -2. That means 4 - 6 equals -2.</p>

<p>If we add or subtract a negative number, the white knight would move in the <i>opposite</i> direction. If you add a negative number, the knight moves to the <i>left</i>. If you subtract a negative number, the knight moves to the <i>right</i>. The expression -6 - -4 would be equal to -2. The knight starts at -6 and moves to the <i>right</i> by 4 spaces. Notice that -6 - -4 has the same answer as -6 + 4.</p>

<p class='centeredImageP'><img src='images/9_numberline4.png' class='centeredImage'></p>

<p>The number line is the same as the X-axis. If we made the number line go up and down instead of left and right, it would model the Y-axis. Adding a positive number (or subtracting a negative number) would move the knight up the number line, and subtracting a positive number (or adding a negative number) would move the knight down. When we put these two number lines together, we have a Cartesian coordinate system.</p>

<p class='centeredImageP'><img src='images/9_cartesian.png' class='centeredImage'></p>

<p>The 0, 0 coordinate has a special name and is called the <span class='term'>origin</span>.</p>

<h2>Changing the Signs</h2>

<p>Subtracting negative numbers or adding negative numbers may seem easy when you have a number line in front of you, but it is also easy when you only have the numbers too. Here are three tricks you can do to make evaluating these expressions easier to do.</p>

<p>The first is if you are adding a negative number, for example, 4 + -2. The first trick is "a minus eats the plus sign on its left". When you see a minus sign with a plus sign on the left, you can replace the plus sign with a minus sign. The answer is still the same, because adding a negative value is the same as subtracting a positive value. 4 + -2 and 4 - 2 both evaluate to 2.</p>

<p class='centeredImageP'><img src='images/9_mathtricka.png' class='centeredImage'></p>

<p>The second trick is if you are subtracting a negative number, for example, 4 - -2. The second trick is "two minuses combine into a plus". When you see the two minus signs next to each other without a number in between them, they can combine into a plus sign. The answer is still the same, because subtracting a negative value is the same as adding a positive value.</p>

<p class='centeredImageP'><img src='images/9_mathtrickb.png' class='centeredImage'></p>

<p>A third trick is to remember that when you add two numbers like 6 and 4, it doesn't matter what order they are in. (This is called the <span class='term'>commutative property</span> of addition.) That means that 6 + 4 and 4 + 6 both equal the same value, 10.</p>

<p class='centeredImageP'><img src='images/9_commutative.png' class='centeredImage'></p>

<p>Say you are adding a negative number and a positive number, like -6 + 8. Because you are adding numbers, you can swap the order of the numbers without changing the answer. -6 + 8 is the same as 8 + -6. But when you look at 8 + -6, you see that the minus sign can eat the plus sign to its left, and the problem becomes 8 - 6. This is easy subtraction, the answer is 2. But this means that -6 + 8 is also 2! We've rearranged the problem to have the same answer, but made it easier to solve.</p>

<p class='centeredImageP'><img src='images/9_mathtrick2.png' class='centeredImage'></p>

<p>Of course, you can always use the interactive shell as a calculator to evaluate these expressions. It is still very useful to know the above three tricks when adding or subtracting negative numbers. After all, you won't always be in front of a computer with Python all the time!</p>

<p class='centeredImageP'><img src='images/9_shellascalculator.png' class='centeredImage'></p>


<h2>Absolute Values</h2>

<p>The <span class='term'>absolute value</span> of a number is the number without the negative sign in front of it. This means that positive numbers do not change, but negative numbers become the same as their twin positive number. For example, the absolute value of -4 is 4. The absolute value of -7 is 7. The absolute value of 5 (which is positive) is just 5.</p>

<p>We can find how far away two things on a number line are from each other by taking the absolute value of their difference. Imagine that the white knight is at position 4 and the black knight is at position -2. To find out the distance between them, you would find the difference by subtracting their positions and taking the absolute value of that number.</p>

<p>It works no matter what the order of the numbers is. -2 - 4 (that is, negative two minus four) is -6, and the absolute value of -6 is 6. However, 4 - -2 (that is, four minus negative two) is 6, and the absolute value of 6 is 6. Using the absolute value of the difference is a good way of finding the distance between two points on a number line (or axis).</p>

<h2>Coordinate System of a Computer Monitor</h2>

<p>It is common that computer monitors use a coordinate system that has the origin at the top left corner of the screen, which increases going down and to the right. There are no negative coordinates. This is because text is printed starting at the top left, and is printed going to the right and downwards. Most computer graphics use this coordinate system, and we will use it in our games. Also it is common to assume that monitors can display 80 text characters per row and 25 text characters per column. This used to be the maximum screen size that monitors could support. While today's monitors can usually display much more text, we will not assume that the user's screen is bigger than 80 by 25.</p>

<p class='centeredImageP'><img src='images/9_monitor.png' class='centeredImage'></p>

<h2>Sample Run</h2>

<p>To keep the length of this book short, the middle part of this game has been cut out.</p>

<blockquote class="samplerun" style='font-size: xx-small'>
S O N A R !<br/>
<br/>
Would you like to view the instructions? (yes/no)<br/>
<span class="sampleruninput">no</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5<br/>
&nbsp;&nbsp;&nbsp;012345678901234567890123456789012345678901234567890123456789<br/>
<br/>
&nbsp;0 `~~~`~~~`~`~~`~~~~~`~``~~~~`~`~~~`~``~``~~````~`~```~`~~~~`` 0<br/>
&nbsp;1 ~`~~~```~~~~`~`~~`~``~`~~```~`~`~~`~`~~~~~~`~`````~`~~`~~~~` 1<br/>
&nbsp;2 `~``~``~~~`~``~`~`~``~`````~~~~~~~~~`~`~~`~``~~~~~```~~`~``` 2<br/>
&nbsp;3 ``~`~~``~`~``~`~`~`~~`~`~~`~`~``~~~`~``~````~``````~~~~``~`` 3<br/>
&nbsp;4 ``~~`~~~``~``~~````~`~`~`~``~~~``~~```~`~~`~~`~`~`~~`~~~~``` 4<br/>
&nbsp;5 ~~```~~~`~`~~``~`~``~```~`~~`~~~~~`~~``~`~`~~~`~~`~`~`~`~~~` 5<br/>
&nbsp;6 ``~~`````~~~~`~`~~~```~~~~`~~`~~`~~```~~`~~~`~~~``~`~~~``~~~ 6<br/>
&nbsp;7 `~`````````~```~``~``~~`~~~~`~~``~``~~~```~`~~`~``~``~~```~~ 7<br/>
&nbsp;8 `~````~```~`~~`~~~`~~``~~~``~`~``~~~``~`~`````~`~~```~`~~~~` 8<br/>
&nbsp;9 ~```~~`~`~``~``~~``~``~```~`~``~~~~`~`~`~~~`~`~`~`~~~``~~``` 9<br/>
10 ```~`~```~``~``~`~~`~``~````~``~~~`~~`~~``~~~~`~~~`~`~~````~ 10<br/>
11 ```~```~~~`~```~~`~~~`~`````~`~~`~`~~`~~`~`~~`~~~````~````~` 11<br/>
12 ~~~`~`~~~``~~~~~~`~~~``~`~`~~`~`~~`~```~~~```~~`~~`~``~``~`~ 12<br/>
13 `~~````~~``~```~~~`~```~`~~~~~~~~~`~~``~~~~~`````~`~`~``~~~~ 13<br/>
14 `~~`~`~````~```~`~`~```~~`~~~~`~```~``~``~``~~~````~~``````~ 14<br/>
<br/>
&nbsp;&nbsp;&nbsp;012345678901234567890123456789012345678901234567890123456789<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5<br/>
You have 16 sonar devices left.&nbsp;3 treasure chests remaining.<br/>
Where do you want to drop the next sonar device? (0-59 0-14) (or type quit)<br/>
<span class="sampleruninput">10 10</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5<br/>
&nbsp;&nbsp;&nbsp;012345678901234567890123456789012345678901234567890123456789<br/>
<br/>
&nbsp;0 `~~~`~~~`~`~~`~~~~~`~``~~~~`~`~~~`~``~``~~````~`~```~`~~~~`` 0<br/>
&nbsp;1 ~`~~~```~~~~`~`~~`~``~`~~```~`~`~~`~`~~~~~~`~`````~`~~`~~~~` 1<br/>
&nbsp;2 `~``~``~~~`~``~`~`~``~`````~~~~~~~~~`~`~~`~``~~~~~```~~`~``` 2<br/>
&nbsp;3 ``~`~~``~`~``~`~`~`~~`~`~~`~`~``~~~`~``~````~``````~~~~``~`` 3<br/>
&nbsp;4 ``~~`~~~``~``~~````~`~`~`~``~~~``~~```~`~~`~~`~`~`~~`~~~~``` 4<br/>
&nbsp;5 ~~```~~~`~`~~``~`~``~```~`~~`~~~~~`~~``~`~`~~~`~~`~`~`~`~~~` 5<br/>
&nbsp;6 ``~~`````~~~~`~`~~~```~~~~`~~`~~`~~```~~`~~~`~~~``~`~~~``~~~ 6<br/>
&nbsp;7 `~`````````~```~``~``~~`~~~~`~~``~``~~~```~`~~`~``~``~~```~~ 7<br/>
&nbsp;8 `~````~```~`~~`~~~`~~``~~~``~`~``~~~``~`~`````~`~~```~`~~~~` 8<br/>
&nbsp;9 ~```~~`~`~``~``~~``~``~```~`~``~~~~`~`~`~~~`~`~`~`~~~``~~``` 9<br/>
10 ```~`~```~5`~``~`~~`~``~````~``~~~`~~`~~``~~~~`~~~`~`~~````~ 10<br/>
11 ```~```~~~`~```~~`~~~`~`````~`~~`~`~~`~~`~`~~`~~~````~````~` 11<br/>
12 ~~~`~`~~~``~~~~~~`~~~``~`~`~~`~`~~`~```~~~```~~`~~`~``~``~`~ 12<br/>
13 `~~````~~``~```~~~`~```~`~~~~~~~~~`~~``~~~~~`````~`~`~``~~~~ 13<br/>
14 `~~`~`~````~```~`~`~```~~`~~~~`~```~``~``~``~~~````~~``````~ 14<br/>
<br/>
&nbsp;&nbsp;&nbsp;012345678901234567890123456789012345678901234567890123456789<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5<br/>
Treasure detected at a distance of&nbsp;5 from the sonar device.<br/>
You have 15 sonar devices left.&nbsp;3 treasure chests remaining.<br/>
Where do you want to drop the next sonar device? (0-59 0-14) (or type quit)<br/>
<span class="sampleruninput">15 6</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5<br/>
&nbsp;&nbsp;&nbsp;012345678901234567890123456789012345678901234567890123456789<br/>
<br/>
&nbsp;0 `~~~`~~~`~`~~`~~~~~`~``~~~~`~`~~~`~``~``~~````~`~```~`~~~~`` 0<br/>
&nbsp;1 ~`~~~```~~~~`~`~~`~``~`~~```~`~`~~`~`~~~~~~`~`````~`~~`~~~~` 1<br/>
&nbsp;2 `~``~``~~~`~``~`~`~``~`````~~~~~~~~~`~`~~`~``~~~~~```~~`~``` 2<br/>
&nbsp;3 ``~`~~``~`~``~`~`~`~~`~`~~`~`~``~~~`~``~````~``````~~~~``~`` 3<br/>
&nbsp;4 ``~~`~~~``~``~~````~`~`~`~``~~~``~~```~`~~`~~`~`~`~~`~~~~``` 4<br/>
&nbsp;5 ~~```~~~`~`~~``~`~``~```~`~~`~~~~~`~~``~`~`~~~`~~`~`~`~`~~~` 5<br/>
&nbsp;6 ``~~`````~~~~`~4~~~```~~~~`~~`~~`~~```~~`~~~`~~~``~`~~~``~~~ 6<br/>
&nbsp;7 `~`````````~```~``~``~~`~~~~`~~``~``~~~```~`~~`~``~``~~```~~ 7<br/>
&nbsp;8 `~````~```~`~~`~~~`~~``~~~``~`~``~~~``~`~`````~`~~```~`~~~~` 8<br/>
&nbsp;9 ~```~~`~`~``~``~~``~``~```~`~``~~~~`~`~`~~~`~`~`~`~~~``~~``` 9<br/>
10 ```~`~```~5`~``~`~~`~``~````~``~~~`~~`~~``~~~~`~~~`~`~~````~ 10<br/>
11 ```~```~~~`~```~~`~~~`~`````~`~~`~`~~`~~`~`~~`~~~````~````~` 11<br/>
12 ~~~`~`~~~``~~~~~~`~~~``~`~`~~`~`~~`~```~~~```~~`~~`~``~``~`~ 12<br/>
13 `~~````~~``~```~~~`~```~`~~~~~~~~~`~~``~~~~~`````~`~`~``~~~~ 13<br/>
14 `~~`~`~````~```~`~`~```~~`~~~~`~```~``~``~``~~~````~~``````~ 14<br/>
<br/>
&nbsp;&nbsp;&nbsp;012345678901234567890123456789012345678901234567890123456789<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5<br/>
Treasure detected at a distance of&nbsp;4 from the sonar device.<br/>
You have 14 sonar devices left.&nbsp;3 treasure chests remaining.<br/>
Where do you want to drop the next sonar device? (0-59 0-14) (or type quit)<br/>
<span class="sampleruninput">15 10</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5<br/>
&nbsp;&nbsp;&nbsp;012345678901234567890123456789012345678901234567890123456789<br/>
<br/>
&nbsp;0 `~~~`~~~`~`~~`~~~~~`~``~~~~`~`~~~`~``~``~~````~`~```~`~~~~`` 0<br/>
&nbsp;1 ~`~~~```~~~~`~`~~`~``~`~~```~`~`~~`~`~~~~~~`~`````~`~~`~~~~` 1<br/>
&nbsp;2 `~``~``~~~`~``~`~`~``~`````~~~~~~~~~`~`~~`~``~~~~~```~~`~``` 2<br/>
&nbsp;3 ``~`~~``~`~``~`~`~`~~`~`~~`~`~``~~~`~``~````~``````~~~~``~`` 3<br/>
&nbsp;4 ``~~`~~~``~``~~````~`~`~`~``~~~``~~```~`~~`~~`~`~`~~`~~~~``` 4<br/>
&nbsp;5 ~~```~~~`~`~~``~`~``~```~`~~`~~~~~`~~``~`~`~~~`~~`~`~`~`~~~` 5<br/>
&nbsp;6 ``~~`````~~~~`~O~~~```~~~~`~~`~~`~~```~~`~~~`~~~``~`~~~``~~~ 6<br/>
&nbsp;7 `~`````````~```~``~``~~`~~~~`~~``~``~~~```~`~~`~``~``~~```~~ 7<br/>
&nbsp;8 `~````~```~`~~`~~~`~~``~~~``~`~``~~~``~`~`````~`~~```~`~~~~` 8<br/>
&nbsp;9 ~```~~`~`~``~``~~``~``~```~`~``~~~~`~`~`~~~`~`~`~`~~~``~~``` 9<br/>
10 ```~`~```~O`~``O`~~`~``~````~``~~~`~~`~~``~~~~`~~~`~`~~````~ 10<br/>
11 ```~```~~~`~```~~`~~~`~`````~`~~`~`~~`~~`~`~~`~~~````~````~` 11<br/>
12 ~~~`~`~~~``~~~~~~`~~~``~`~`~~`~`~~`~```~~~```~~`~~`~``~``~`~ 12<br/>
13 `~~````~~``~```~~~`~```~`~~~~~~~~~`~~``~~~~~`````~`~`~``~~~~ 13<br/>
14 `~~`~`~````~```~`~`~```~~`~~~~`~```~``~``~``~~~````~~``````~ 14<br/>
<br/>
&nbsp;&nbsp;&nbsp;012345678901234567890123456789012345678901234567890123456789<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5<br/>
You have found a sunken treasure chest!<br/>
You have 13 sonar devices left.&nbsp;2 treasure chests remaining.<br/>
Where do you want to drop the next sonar device? (0-59 0-14) (or type quit)<br/>
<br/>
<br/>
...skipped over for brevity....<br/>
<br/>
<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5<br/>
&nbsp;&nbsp;&nbsp;012345678901234567890123456789012345678901234567890123456789<br/>
<br/>
&nbsp;0 `~~~`~~~`~`~~`~~~~~`~``~~~~`~`~~~`~``~``~~````~`~```~`~~~~`` 0<br/>
&nbsp;1 ~`~~~```~~~~`~`~~`~``~`~~```~O~`~~`~`~~~~~~`~`````~`~~`~~~~` 1<br/>
&nbsp;2 `~``~``~~~`~``~`~`~``~`````~~O~~~O~~`~`~~`~``~~~~~```~~`~``` 2<br/>
&nbsp;3 ``~3~~``8`~``~`~`~`~~`~`~~`~`~``~~~`~`O~````~``````~~~~``~`` 3<br/>
&nbsp;4 ``~~`~~~``~``~~````~`~`~`~O`~~O``~~```~`~~`~~`~`~`~~`~~~~``` 4<br/>
&nbsp;5 ~~```~~~`~`~~``~`~``~```~`~~`~~~~~`~~``~`~`~~~`~~`~`~`~`~~~` 5<br/>
&nbsp;6 ``~~`````~~~~`~O~~~```~~~~`~~`~~`~~```~~`~~~`~~~``O`~~~``~~~ 6<br/>
&nbsp;7 `~`````````~```~``~``~~`~~~~`~~``~``~~~```~`~~`~``~``~~```~~ 7<br/>
&nbsp;8 `~````~```~`~~`~~~`~~``~~~``~`~``~~~``~`O```0`~`~~```~`~~~~` 8<br/>
&nbsp;9 ~```~~`~`~``~``~~``~``~```~O~``~~~~`~`~`~~~`~`~`~`~~~``~~``` 9<br/>
10 ```~`~```~O`~``O`~~`~``~````~``~~~`~~`~~``~~~~`~~~`~`~~````~ 10<br/>
11 ```~```~~~`~```~~`~~~`~`````~`~~`~`~~`~~`~`~~`~~~````~````~` 11<br/>
12 ~~~`~`~~~``~~~~~~`~~~``~`~`~~`~`~~`~```~~~```~~`~~`~``~``~`~ 12<br/>
13 `~~````~~``~```~~~`~```~`~~~~~~~~~`~~``~~~~~`````~`~`~``~~~~ 13<br/>
14 `~~`~`~````~```~`~`~```~~`~~~~`~```~``~``~``~~~````~~``````~ 14<br/>
<br/>
&nbsp;&nbsp;&nbsp;012345678901234567890123456789012345678901234567890123456789<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5<br/>
Treasure detected at a distance of&nbsp;4 from the sonar device.<br/>
We've run out of sonar devices! Now we have to turn the ship around and head<br/>
for home with treasure chests still out there! Game over.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;The remaining chests were here:<br/>
&nbsp;&nbsp;&nbsp;&nbsp;0, 4<br/>
Do you want to play again? (yes or no)<br/>
<span class="sampleruninput">no</span><br/>
</blockquote>

<h2>Source Code</h2>

<p>Knowing about Cartesian coordinates, number lines, negative numbers, and absolute values will help us out with our Sonar game. Here is the source code for the game. Type it into a new file, then save the file as sonar.py and run it by pressing the F5 key. You do not need to understand the code to type it in or play the game, the source code will be explained later.</p>

<blockquote class="sourcecode"><span class='sourcecodeHeader'>sonar.py</span><br/>
<ol start=1>
<li># Sonar</li>
<li></li>
<li>import random</li>
<li>import sys</li>
<li></li>
<li>def drawBoard(board):</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;# Draw the board data structure.</li>
<li></li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;hline = '&nbsp;&nbsp;&nbsp;&nbsp;' # initial space for the numbers down the left side of the board</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;for i in range(1, 6):</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hline += (' ' * 9) + str(i)</li>
<li></li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;# print the numbers across the top&nbsp;&nbsp;&nbsp;&nbsp;</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;print hline</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;print '&nbsp;&nbsp;&nbsp;' + ('0123456789' * 6)</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;print</li>
<li></li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;# print each of the 15 rows</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;for i in range(15):</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# single-digit numbers need to be padded with an extra space</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if i < 10:</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;extraSpace = ' '</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else:</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;extraSpace = ''</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print '%s%s %s %s' % (extraSpace, i, getRow(board, i), i)</li>
<li></li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;# print the numbers across the bottom</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;print</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;print '&nbsp;&nbsp;&nbsp;' + ('0123456789' * 6)</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;print hline</li>
<li></li>
<li></li>
<li>def getRow(board, row):</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;# Return a string from the board data structure at a certain row.</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;boardRow = ''</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;for i in range(60):</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;boardRow += board[i][row]</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;return boardRow</li>
<li></li>
<li>def getNewBoard():</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;# Create a new 60x15 board data structure.</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;board = []</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;for x in range(60): # the main list is a list of 60 lists</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;board.append([])</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for y in range(15): # each list in the main list has 15 single-character strings</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# use different characters for the ocean to make it more readable.</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if random.randint(0, 1) == 0:</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;board[x].append('~')</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else:</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;board[x].append('`')</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;return board</li>
<li></li>
<li>def getRandomChests(numChests):</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;# Create a list of chest data structures (two-item lists of x, y int coordinates)</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;chests = []</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;for i in range(numChests):</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;chests.append([random.randint(0, 59), random.randint(0, 14)])</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;return chests</li>
<li></li>
<li>def isValidMove(x, y):</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;# Return True if the coordinates are on the board, otherwise False.</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;return x >= 0 and x &lt;= 59 and y >= 0 and y &lt;= 14</li>
<li></li>
<li>def makeMove(board, chests, x, y):</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;# Change the board data structure with a sonar device character. Remove treasure chests</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;# from the chests list as they are found. Return False if this is an invalid move.</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;# Otherwise, return the string of the result of this move.</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;if not isValidMove(x, y):</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return False</li>
<li></li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;smallestDistance = 100 # any chest will be closer than 100.</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;for cx, cy in chests:</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if abs(cx - x) > abs(cy - y):</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;distance = abs(cx - x)</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else:</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;distance = abs(cy - y)</li>
<li></li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if distance < smallestDistance: # we want the closest treasure chest.</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;smallestDistance = distance</li>
<li></li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;if smallestDistance == 0:</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# xy is directly on a treasure chest!</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;chests.remove([x, y])</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return 'You have found a sunken treasure chest!'</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;else:</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if smallestDistance < 10:</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;board[x][y] = str(smallestDistance)</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return 'Treasure detected at a distance of %s from the sonar device.' % (smallestDistance)</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else:</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;board[x][y] = 'O'</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return 'Sonar did not detect anything. All treasure chests out of range.'</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </li>
<li></li>
<li>def enterPlayerMove():</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;# Let the player type in their move. Return a two-item list of int xy coordinates.</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;print 'Where do you want to drop the next sonar device? (0-59 0-14) (or type quit)'</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;while True:</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;move = raw_input()</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if move.lower() == 'quit':</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print 'Thanks for playing!'</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sys.exit()</li>
<li></li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;move = move.split()</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if len(move) == 2 and move[0].isdigit() and move[1].isdigit() and isValidMove(int(move[0]), int(move[1])):</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return [int(move[0]), int(move[1])]</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print 'Enter a number from 0 to 59, a space, then a number from 0 to 14.'</li>
<li></li>
<li></li>
<li>def playAgain():</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;# This function returns True if the player wants to play again, otherwise it returns False.</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;print 'Do you want to play again? (yes or no)'</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;return raw_input().lower().startswith('y')</li>
<li></li>
<li></li>
<li>def showInstructions():</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;print '''Instructions:</li>
<li>You are the captain of the Simon, a treasure-hunting ship. Your current mission</li>
<li>is to find the three sunken treasure chests that are lurking in the part of the</li>
<li>ocean you are in and collect them.</li>
<li></li>
<li>To play, enter the coordinates of the point in the ocean you wish to drop a</li>
<li>sonar device. The sonar can find out how far away the closest chest is to it.</li>
<li>For example, the d below marks where the device was dropped, and the 2's</li>
<li>represent distances of 2 away from the device. The 4's represent</li>
<li>distances of 4 away from the device.</li>
<li></li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;444444444</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;4 22222 4</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;4 2&nbsp;&nbsp;&nbsp;2 4</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;4 2 d 2 4</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;4 2&nbsp;&nbsp;&nbsp;2 4</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;4 22222 4</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;444444444</li>
<li>Press enter to continue...'''</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;raw_input()</li>
<li></li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;print '''For example, here is a treasure chest (the c) located a distance of 2 away</li>
<li>from the sonar device (the d):</li>
<li></li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;22222</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;c&nbsp;&nbsp;&nbsp;2</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;2 d 2</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;2</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;22222</li>
<li></li>
<li>The point where the device was dropped will be marked with a 2.</li>
<li></li>
<li>The treasure chests don't move around. Sonar devices can detect treasure</li>
<li>chests up to a distance of 9. If all chests are out of range, the point</li>
<li>will be marked with O</li>
<li></li>
<li>If a device is directly dropped on a treasure chest, you have discovered </li>
<li>the location of the chest, and it will be collected. The sonar device will</li>
<li>remain there.</li>
<li></li>
<li>When you collect a chest, all sonar devices will update to locate the next</li>
<li>closest sunken treasure chest.</li>
<li>Press enter to continue...'''</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;raw_input()</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;print</li>
<li></li>
<li></li>
<li>print 'S O N A R !'</li>
<li>print</li>
<li>print 'Would you like to view the instructions? (yes/no)'</li>
<li>if raw_input().lower().startswith('y'):</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;showInstructions()</li>
<li></li>
<li>while True:</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;# game setup</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;sonarDevices = 16</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;theBoard = getNewBoard()</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;theChests = getRandomChests(3)</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;drawBoard(theBoard)</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;previousMoves = []</li>
<li></li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;while sonarDevices > 0:</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# Start of a turn:</li>
<li></li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# sonar device/chest status</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if sonarDevices > 1: extraSsonar = 's'</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else: extraSsonar = ''</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if len(theChests) > 1: extraSchest = 's'</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else: extraSchest = ''</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print 'You have %s sonar device%s left. %s treasure chest%s remaining.' % (sonarDevices, extraSsonar, len(theChests), extraSchest)</li>
<li></li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;x, y = enterPlayerMove()</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;previousMoves.append([x, y]) # we must track all moves so that sonar devices can be updated.</li>
<li></li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;moveResult = makeMove(theBoard, theChests, x, y)</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if moveResult == False:</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;continue</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else:</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if moveResult == 'You have found a sunken treasure chest!':</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# update all the sonar devices currently on the map.</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for x, y in previousMoves:</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;makeMove(theBoard, theChests, x, y)</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;drawBoard(theBoard)</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print moveResult</li>
<li></li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if len(theChests) == 0:</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print 'You have found all the sunken treasure chests! Congratulations and good game!'</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break</li>
<li></li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sonarDevices -= 1</li>
<li></li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;if sonarDevices == 0:</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print 'We\'ve run out of sonar devices! Now we have to turn the ship around and head'</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print 'for home with treasure chests still out there! Game over.'</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print '&nbsp;&nbsp;&nbsp;&nbsp;The remaining chests were here:'</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for x, y in theChests:</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print '&nbsp;&nbsp;&nbsp;&nbsp;%s, %s' % (x, y)</li>
<li></li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;if not playAgain():</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sys.exit()</li>
<li></li>
</ol>
</blockquote>

<h2>Designing the Program</h2>

<p>Normally we show the flow chart for a game before you type in the source code. But Sonar is kind of complicated, so you should type in the game and play it a few times first. After you've played the game a few times, you can kind of get an idea of the sequence of events in this game. For your own games, you should draw out the flow chart first to help you figure out what exactly you need to program. Here is a flow chart for the Sonar game:</p>

<p class='centeredImageP'><img src='images/9_rem1.png' class='centeredImage'></p>

<p>It may also help us to write out on paper the things we need our program to do, and come up with some function names that will handle these actions. Remember, this is helpful before we start typing in the source code as a reminder of everything our code needs to do. Otherwise we might end up forgetting a function, or typing in two different functions that do the same thing.</p>

<table align='center' class='simplefulltable'>
<tr><td><b>What the code should do.</b></td><td width='30'>&nbsp;</td><td><b>The function that will do it.</b></td></tr>
<tr><td>Prints the game board on the screen based on the <span class='m'>board</span> data structure it is passed, including the coordinates along the top, bottom, and left and right sides.</td><td width='30'>&nbsp;</td><td><span class='m'>drawBoard()</span></td></tr>
<tr><td>Create a fresh <span class='m'>board</span> data structure.</td><td width='30'>&nbsp;</td><td><span class='m'>getNewBoard()</span></td></tr>
<tr><td>Create a fresh <span class='m'>chests</span> data structure that has a number of chests randomly scattered across the game board.</td><td width='30'>&nbsp;</td><td><span class='m'>getRandomChests()</span></td></tr>
<tr><td>Check that the XY coordinates that are passed to this function are located on the game board or not.</td><td width='30'>&nbsp;</td><td><span class='m'>isValidMove()</span></td></tr>
<tr><td>Let the player type in the XY coordinates of their next move, and keep asking until they type in the coordinates correctly.</td><td width='30'>&nbsp;</td><td><span class='m'>enterPlayerMove()</span></td></tr>
<tr><td>Place a sonar device on the game board, and update the <span class='m'>board</span> data structure then return a string that describes what happened.</td><td width='30'>&nbsp;</td><td><span class='m'>makeMove()</span></td></tr>
<tr><td>Ask the player if they want to play another game of Sonar.</td><td width='30'>&nbsp;</td><td><span class='m'>playAgain()</span></td></tr>
<tr><td>Print out instructions for the game.</td><td width='30'>&nbsp;</td><td><span class='m'>showInstructions()</span></td></tr>
</table>

<p>These might not be all of the functions we need, but a list like this is a good idea to help you get started with programming your own games. For example, when we are writing the <span class='m'>drawBoard()</span> function in the Sonar game, we figure out that we also need a <span class='m'>getRow()</span> function. Writing out a function once and then calling it twice is preferable to writing out the code twice. The whole point of functions is to reduce duplicate code down to one place, so if we ever need to make changes to that code we only need to change one place in our program.</p>

<h2>Code Explanation</h2>

<blockquote class="sourcecode">
<ol start=1>
<li># Sonar</li>
<li></li>
<li>import random</li>
<li>import sys</li>
</ol>
</blockquote>

<p>Here we import two modules, <span class='m'>random</span> and <span class='m'>sys</span>. The <span class='m'>sys</span> module contains the <span class='m'>exit()</span> function, which causes the program to immediately terminate. We will call this function on line 101.</p>

<blockquote class="sourcecode">
<ol start=6>
<li>def drawBoard(board):</li>
</ol>
</blockquote>

<p>The <span class='m'>drawBoard()</span> function is the first function we will define for our program. The sonar game's board is an ASCII-art ocean with coordinates going along the X- and Y-axis, and looks like this:</p>

<blockquote style="font-family: courier; font-size: xx-small;">
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5<br/>
&nbsp;&nbsp;&nbsp;012345678901234567890123456789012345678901234567890123456789<br/>
<br/>
&nbsp;0 ~~~`~``~~~``~~~~``~`~`~`~`~~`~~~`~~`~``````~~`~``~`~~```~`~` 0<br/>
&nbsp;1 `~`~````~~``~`~```~```~```~`~~~``~~`~~~``````~`~``~~``~~`~~` 1<br/>
&nbsp;2 ```~~~~`~`~~```~~~``~````~~`~`~~`~`~`~```~~`~``~~`~`~~~~~~`~ 2<br/>
&nbsp;3 ~~~~`~~~``~```~``~~`~`~~`~`~~``~````~`~````~```~`~`~`~`````~ 3<br/>
&nbsp;4 ~```~~~~~`~~````~~~~```~~~`~`~`~````~`~~`~`~~``~~`~``~`~``~~ 4<br/>
&nbsp;5 `~```~`~`~~`~~~```~~``~``````~~``~`~`~~~~`~~``~~~~~~`~```~~` 5<br/>
&nbsp;6 ``~~`~~`~``~`````~````~~``~`~~~~`~~```~~~``~`~`~~``~~~```~~~ 6<br/>
&nbsp;7 ``~``~~~~~~```~`~```~~~``~`~``~`~~~~~~```````~~~`~~`~~`~~`~~ 7<br/>
&nbsp;8 ~~`~`~~```~``~~``~~~``~~`~`~~`~`~```~```~~~```~~~~~~`~`~~~~` 8<br/>
&nbsp;9 ```~``~`~~~`~~```~``~``~~~```~````~```~`~~`~~~~~`~``~~~~~``` 9<br/>
10 `~~~~```~`~````~`~`~~``~`~~~~`~``~``~```~~```````~`~``~````` 10<br/>
11 ~~`~`~~`~``~`~~~````````````````~~`````~`~~``~`~~~~`~~~`~~`~ 11<br/>
12 ~~`~~~~```~~~`````~~``~`~`~~``````~`~~``~```````~~``~~~`~~`~ 12<br/>
13 `~``````~~``~`~~~```~~~~```~~`~`~~~`~```````~~`~```~``~`~~~~ 13<br/>
14 ~~~``~```~`````~~`~`~``~~`~``~`~~`~`~``~`~``~~``~`~``~```~~~ 14<br/>
<br/>
&nbsp;&nbsp;&nbsp;012345678901234567890123456789012345678901234567890123456789<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5<br/>
</blockquote>

<p>The backtick (`) and tilde (~) characters are located next to the 1 key on your keyboard. They are suppose to resemble the waves of the ocean. Somewhere in this ocean are three treasure chests, but you don't know where. You have to figure it out by planting sonar devices, and you can tell the game program where by typing in the X and Y coordinates (which are printed on the four sides of the screen.)</p>

<p>We will split up the drawing in the <span class='m'>drawBoard()</span> function into four steps. First, we create a string variable of the line with 1, 2, 3, 4, and 5 spaced out with wide gaps. Second, we use that string to display the X-axis coordinates along the top of the screen. Third, we print each row of the ocean along with the Y-axis coordinates on both sides of the screen. And fourth, we print out the X-axis again at the bottom. Having the coordinates on all sides makes it easier for the player to move their finger along the spaces to see where exactly they want to plan a sonar device.</p>

<blockquote class="sourcecode">
<ol start=7>
<li>&nbsp;&nbsp;&nbsp;&nbsp;# Draw the board data structure.</li>
<li></li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;hline = '&nbsp;&nbsp;&nbsp;&nbsp;' # initial space for the numbers down the left side of the board</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;for i in range(1, 6):</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hline += (' ' * 9) + str(i)</li>
</ol>
</blockquote>

<p>Let's look again at the top part of the board, this time with red plus signs instead of blank spaces so we can count the spaces easier:</p>

<img src="images/9_widetext2.png"><br/>

<!--<blockquote style="font-family: courier;">
<font color="FF0000">+++++++++++++</font>1<font color="FF0000">+++++++++</font>2<font color="FF0000">+++++++++</font>3<font color="FF0000">+++++++++</font>4<font color="FF0000">+++++++++</font>5 <font color="FF0000"># first line</font><br/>
<font color="FF0000">+++</font>012345678901234567890123456789012345678901234567890123456789 <font color="FF0000"># second line</font><br/>
<br/>
<font color="FF0000">+</font>0 ~~~`~``~~~``~~~~``~`~`~`~`~~`~~~`~~`~``````~~`~``~`~~```~`~` 0 <font color="FF0000"># third line</font><br/>
</blockquote>-->

<p>As you can see, the numbers on the first line which mark the tens position all have nine spaces in between them, and there are thirteen spaces in front of the 1. We are going to create a string with this line and store it in a variable named <span class='m'>hline</span>.</p>


<blockquote class="sourcecode">
<ol start=13>
<li>&nbsp;&nbsp;&nbsp;&nbsp;# print the numbers across the top&nbsp;&nbsp;&nbsp;&nbsp;</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;print hline</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;print '&nbsp;&nbsp;&nbsp;' + ('0123456789' * 6)</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;print</li>
<li></li>
</ol>
</blockquote>

<p>To print the numbers across the top of the sonar board, we first print the contents of the <span class='m'>hline</span> variable. Then on the next line, we print three spaces (so that this row lines up correctly), and then the string <span class='m'><wbr>'012345678901234567890123456789012345678901234567890123456789'</wbr></span>. But this is tedious to type into the source, so instead we type <span class='m'>('0123456789' * 6)</span> which evaluates to the same string.</p>

<blockquote class="sourcecode">
<ol start=18>
<li>&nbsp;&nbsp;&nbsp;&nbsp;# print each of the 15 rows</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;for i in range(15):</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# single-digit numbers need to be padded with an extra space</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if i < 10:</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;extraSpace = ' '</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else:</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;extraSpace = ''</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print '%s%s %s %s' % (extraSpace, i, getRow(board, i), i)</li>
</ol>
</blockquote>

<p>Now we print the each row of the board, including the numbers down the side to label the Y-axis. We use the <span class='m'>for</span> loop to print rows 0 through 14 on the board, along with the row numbers on either side of the board.</p>

<p>We have a small problem. Numbers with only one digit (like 0, 1, 2, and so on) only take up one space when we print them out, but numbers with two digits (like 10, 11, and 12) take up two spaces. This means the rows might not line up and would look like this:</p>

<blockquote style="font-family: courier; font-size: xx-small;">
8 ~~`~`~~```~``~~``~~~``~~`~`~~`~`~```~```~~~```~~~~~~`~`~~~~` 8<br/>
9 ```~``~`~~~`~~```~``~``~~~```~````~```~`~~`~~~~~`~``~~~~~``` 9<br/>
10 `~~~~```~`~````~`~`~~``~`~~~~`~``~``~```~~```````~`~``~````` 10<br/>
11 ~~`~`~~`~``~`~~~````````````````~~`````~`~~``~`~~~~`~~~`~~`~ 11<br/>
</blockquote>

<p>The solution is easy, we just add a space in front of all the single-digit numbers. This is what the <span class='m'>if-else</span> statement that starts on line 21 of our code does. We will print the variable <span class='m'>extraSpace</span> when we print the row, and if <span class='m'>i</span> is less than <span class='m'>10</span> (which means it will have only one digit), we assign a single space string to <span class='m'>extraSpace</span>. Otherwise, we set <span class='m'>extraSpace</span> to be a blank string. This way, all of our rows will line up when we print them.</p>

<p>The <span class='m'>getRow()</span> function will return a string representing the row number we pass it. Its two parameters are the board data structure stored in the <span class='m'>board</span> variable and a row number. We will look at this function next.</p>

<blockquote class="sourcecode">
<ol start=27>
<li>&nbsp;&nbsp;&nbsp;&nbsp;# print the numbers across the bottom</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;print</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;print '&nbsp;&nbsp;&nbsp;' + ('0123456789' * 6)</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;print hline</li>
</ol>
</blockquote>

<p>This code is similar to lines 14 to 17. This will print the X-axis coordinates along the bottom of the screen.</p>

<blockquote class="sourcecode">
<ol start=33>
<li>def getRow(board, row):</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;# Return a string from the board data structure at a certain row.</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;boardRow = ''</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;for i in range(60):</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;boardRow += board[i][row]</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;return boardRow</li>
</ol>
</blockquote>

<p>This function constructs a string called <span class='m'>boardRow</span> from the characters stored in <span class='m'>board</span>. First we set <span class='m'>boardRow</span> to the blank string. The row number (which is the Y coordinate) is passed as a parameter. The string we want is made by concatenating <span class='m'>board[0][row]</span>, <span class='m'>board[1][row]</span>, <span class='m'>board[2][row]</span>, and so on up to <span class='m'>board[59][row]</span>. (This is because the row is made up of 60 characters, from index 0 to index 59.)</p>

<p>The <span class='m'>for</span> loop iterates from integers <span class='m'>0</span> to <span class='m'>59</span>. On each iteration the next character in the <span class='m'>board</span> data structure is copied on to the end of <span class='m'>boardRow</span>. By the time the loop is done, <span class='m'>extraSpace</span> is fully formed, so we return it.</p>

<blockquote class="sourcecode">
<ol start=40>
<li>def getNewBoard():</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;# Create a new 60x15 board data structure.</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;board = []</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;for x in range(60): # the main list is a list of 60 lists</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;board.append([])</li>
</ol>
</blockquote>

<p>At the start of each new game, we will need a fresh <span class='m'>board</span> data structure. The <span class='m'>board</span> data structure is a list of lists of strings. The first list represents the X coordinate. Since our game's board is 60 characters across, this first list needs to contain 60 lists. So we create a <span class='m'>for</span> loop that will append 60 blank lists to it.</p>

<blockquote class="sourcecode">
<ol start=45>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for y in range(15): # each list in the main list has 15 single-character strings</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# use different characters for the ocean to make it more readable.</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if random.randint(0, 1) == 0:</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;board[x].append('~')</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else:</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;board[x].append('`')</li>
</ol>
</blockquote>

<p>But <span class='m'>board</span> is more than just a list of 60 blank lists. Each of the 60 lists represents the Y coordinate of our game board. There are 15 rows in the board, so each of these 60 lists must have 15 characters in them. We have another <span class='m'>for</span> loop to add 15 single-character strings that represent the ocean. The "ocean" will just be a bunch of <span class='m'>'~'</span> and <span class='m'>'`'</span> strings, so we will randomly choose between those two. We can do this by generating a random number between <span class='m'>0</span> and <span class='m'>1</span> with a call to <span class='m'>random.randint()</span>. If the return value of <span class='m'>random.randint()</span> is <span class='m'>0</span>, we add the <span class='m'>'~'</span> string. Otherwise we will add the <span class='m'>'`'</span> string.</p>

<p>This is like deciding which character to use by tossing a coin. And since the return value from <span class='m'>random.randint()</span> will be 0 about half the time, half of the ocean characters will be <span class='m'>'~'</span> and the other half will be <span class='m'>'`'</span>. This will give our ocean a nice random, choppy look to it.</p>

<p>Remember that <span class='m'>board</span> variable is a list of 60 lists that have 15 strings. That means to get the string at coordinate 26, 12, we would access <span class='m'>board[26][12]</span>, and not <span class='m'>board[12][26]</span>. The X coordinate is first, then the Y coordinate. We could have made <span class='m'>board</span> a list of 15 lists of 60 characters, but then to access the string at coordinate 26, 12 we would have to use <span class='m'>board[12][26]</span>, which would be confusing since the coordinates are reversed.</p>

<p>Here is the picture from the Hangman chapter that demonstrates the indexes of a list of lists named <span class='m'>x</span>. The red arrows point to indexes of the inner lists themselves. The image is also flipped on its side to make it easier to read:</p>

<p class='centeredImageP'><img src='images/6_listoflistsexample.png' class='centeredImage'></p>

<blockquote class="sourcecode">
<ol start=51>
<li>&nbsp;&nbsp;&nbsp;&nbsp;return board</li>
</ol>
</blockquote>

<p>Finally, we return the <span class='m'>board</span> variable. Remember that in this case, we are returning a reference to the list that we made. Any changes we made to the list (or the lists inside the list) in our function will still be there outside of the function.</p>

<blockquote class="sourcecode">
<ol start=53>
<li>def getRandomChests(numChests):</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;# Create a list of chest data structures (two-item lists of x, y int coordinates)</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;chests = []</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;for i in range(numChests):</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;chests.append([random.randint(0, 59), random.randint(0, 14)])</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;return chests</li>
</ol>
</blockquote>

<p>Another task we need to do at the start of the game is decide where the hidden treasure chests are. We will represent the treasure chests in our game as a list of lists of two integers. These two integers will be the X and Y coordinates. For example, if the chest data structure was <span class='m'>[[2, 2], [2, 4], [10, 0]]</span>, then this would mean there are three treasure chests, one at 2, 2, another at 2, 4, and a third one at 10, 0.</p>

<p>We will pass the <span class='m'>numChests</span> parameter to tell the function how many treasure chests we want it to generate. We set up a <span class='m'>for</span> loop to iterate this number of times, and on each iteration we append a list of two random integers. The X coordinate can be anywhere from 0 to 59, and the Y coordinate can be from anywhere between 0 and 14. The expression <span class='m'>[random.randint(0, 59), random.randint(0, 14)]</span> that is passed to the <span class='m'>append</span> method will evaluate to something like <span class='m'>[2, 2]</span> or <span class='m'>[2, 4]</span> or <span class='m'>[10, 0]</span>. This data structure is then returned.</p>

<!-- TODO: Note that a big flaw with this game: it is possible (small chance though) for multiple treasure chests to be in the same spot. -->

<blockquote class="sourcecode">
<ol start=60>
<li>def isValidMove(x, y):</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;# Return True if the coordinates are on the board, otherwise False.</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;return x >= 0 and x &lt;= 59 and y >= 0 and y &lt;= 14</li>
</ol>
</blockquote>

<p>The player will be typing in X and Y coordinates of where they want to drop a sonar device. But they may type in coordinates that do not exist on the game board. The X coordinates must be between 0 and 59, and the Y coordinate must be between 0 and 14. This function uses a simple expression that uses <span class='m'>and</span> operators to ensure that each condition is <span class='m'>True</span>. If just one of these are <span class='m'>False</span>, then the entire expression evaluates to <span class='m'>False</span>. This boolean value is returned by the function.</p>


<blockquote class="sourcecode">
<ol start=64>
<li>def makeMove(board, chests, x, y):</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;# Change the board data structure with a sonar device character. Remove treasure chests</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;# from the chests list as they are found. Return False if this is an invalid move.</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;# Otherwise, return the string of the result of this move.</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;if not isValidMove(x, y):</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return False</li>
</ol>
</blockquote>

<p>In our Sonar game, the game board is updated to display a number for each sonar device dropped. The number shows how far away the closest treasure chest is. So when the player makes a move by giving the program an X and Y coordinate, we will change the board based on the positions of the treasure chests. This is why our <span class='m'>makeMove()</span> function takes four parameters: the game board data structure, the treasure chests data structures, and the X and Y coordinates.</p>

<p>This function will return the <span class='m'>and</span> boolean value if the X and Y coordinates if was passed do not exist on the game board. If <span class='m'>isValidMove()</span> returns <span class='m'>False</span>, then <span class='m'>makeMove()</span> will return <span class='m'>False</span>.</p>

<p>Other than that, <span class='m'>makeMove()</span> will return the string <span class='m'>'You have found a sunken treasure chest!'</span> if the XY coordinates are directly on a treasure chest. If the XY coordinates are within a distance of 9 or less of a treasure chest, we return the string <span class='m'>'Treasure detected at a distance of %s from the sonar device.'</span> (where %s is the distance). Otherwise, <span class='m'>makeMove()</span> will return the string <span class='m'>'Sonar did not detect anything. All treasure chests out of range.'</span>.</p>

<blockquote class="sourcecode">
<ol start=71>
<li>&nbsp;&nbsp;&nbsp;&nbsp;smallestDistance = 100 # any chest will be closer than 100.</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;for cx, cy in chests:</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if abs(cx - x) > abs(cy - y):</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;distance = abs(cx - x)</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else:</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;distance = abs(cy - y)</li>
<li></li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if distance < smallestDistance: # we want the closest treasure chest.</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;smallestDistance = distance</li>
</ol>
</blockquote>

<p>Given the XY coordinates of where the player wants to drop the sonar device, and a list of XY coordinates for the treasure chests (in the <span class='m'>chests</span> list of lists), how do we find out which treasure chest is closest?</p>

<p>While <span class='m'>x</span> and <span class='m'>y</span> are just integers (say, <span class='m'>5</span> and <span class='m'>0</span>), together they represent the location on the game board (which is a Cartesian coordinate system) where the player guessed. And while <span class='m'>chests</span> may have a value like <span class='m'>[[5, 0], [0, 2], [4, 2]]</span>, that value represents the locations of three treasure chests. Even though these variables are just a bunch of numbers, we can visualize it like this:</p>

<p class='centeredImageP'><img src='images/9_board.png' class='centeredImage'></p>

<p>We figure out the distance from the sonar device located at 0, 2 with "rings" and the distances around it (in blue text):</p>

<p class='centeredImageP'><img src='images/9_board2.png' class='centeredImage'></p>

<p>But how do we translate this into code for our game? We need a way to represent distance as an expression. Notice that the distance from an XY coordinate is always the larger of two values: the absolute value of the difference of the two X coordinates and the absolute value of the difference of the two Y coordinates.</p>

<p>That means we should subtract the sonar device's X coordinate and a treasure chest's X coordinate, and then take the absolute value of this number. We do the same for the sonar device's Y coordinate and a treasure chest's Y coordinate. The larger of these two values is the distance. Let's look at our example board with rings above to see if this algorithm is correct.</p>

<p>The sonar's X and Y coordinates are 3 and 2. The first treasure chest's X and Y coordinates (first in the list <span class='m'>[[5, 0], [0, 2], [4, 2]]</span> that is) are 5 and 0.</p>

<p>For the X coordinates, <span class='m'>3 - 5</span> evaluates to <span class='m'>-2</span>, and the absolute value of <span class='m'>-2</span> is <span class='m'>2</span>.</p>

<p>For the Y coordinates, <span class='m'>2 - 1</span> evaluates to <span class='m'>1</span>, and the absolute value of <span class='m'>1</span> is <span class='m'>1</span>. </p>

<p>Comparing the two absolute values <span class='m'>2</span> and <span class='m'>1</span>, <span class='m'>2</span> is the larger value and should be the distance from the sonar device and the treasure chest at coordinates 5, 1. We can look at the board and see that this algorithm works, because the treasure chest at 5,1 is in the sonar device's 2nd ring. Let's quickly compare the other two chests to see if their distances work out correctly also.</p>

<p>Let's find the distance from the sonar device at 3,2 and the treasure chest at 0,2. <span class='m'>abs(3 - 0)</span> evaluates to <span class='m'>3</span>. The <span class='m'>abs()</span> function returns the absolute value of the number we pass to it. <span class='m'>abs(2 - 2)</span> evaluates to <span class='m'>0</span>. <span class='m'>3</span> is larger than <span class='m'>0</span>, so the distance from the sonar device at 3,2 and the treasure chest at 0,2 is <span class='m'>3</span>. We look at the board and see this is true.</p>

<p>Let's find the distance from the sonar device at 3,2 and the last treasure chest at 4,2. <span class='m'>abs(3 - 4)</span> evaluates to <span class='m'>1</span>. <span class='m'>abs(2 - 2)</span> evaluates to <span class='m'>0</span>. <span class='m'>1</span> is larger than <span class='m'>0</span>, so the distance from the sonar device at 3,2 and the treasure chest at 4,2 is <span class='m'>1</span>. We look at the board and see this is true also.</p>

<p>Because all three distances worked out correctly, we can be sure that our algorithm works. The distances from the sonar device to the three sunken treasure chests are <span class='m'>2</span>, <span class='m'>3</span>, and <span class='m'>1</span>. On each guess, we want to know the distance from the sonar device to the closest of the three treasure chest distances. To do this we use a variable called <span class='m'>smallestDistance</span>. Let's look at the code again:</p>

<blockquote class="sourcecode">
<ol start=71>
<li>&nbsp;&nbsp;&nbsp;&nbsp;smallestDistance = 100 # any chest will be closer than 100.</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;for cx, cy in chests:</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if abs(cx - x) > abs(cy - y):</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;distance = abs(cx - x)</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else:</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;distance = abs(cy - y)</li>
<li></li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if distance < smallestDistance: # we want the closest treasure chest.</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;smallestDistance = distance</li>
</ol>
</blockquote>

<p>You can also use multiple assignment in <span class='m'>for</span> loops. For example, the assignment statement <span class='m'>a, b = [5, 10]</span> will assign <span class='m'>5</span> to <span class='m'>a</span> and <span class='m'>10</span> to <span class='m'>b</span>. Also, the <span class='m'>for</span> loop <span class='m'>for i in [0, 1, 2, 3, 4]</span> will assign the <span class='m'>i</span> variable the values <span class='m'>0</span> and <span class='m'>1</span> and so on for each iteration.</p>

<p>The for loop <span class='m'>for cx, cy in chests:</span> combines both of these principles. Because <span class='m'>chests</span> is a list where each item in the list is itself a list of two integers, the first of these integers is assigned to <span class='m'>cx</span> and the second integer is assigned to <span class='m'>cy</span>. So if <span class='m'>chests</span> has the value <span class='m'>[[5, 0], [0, 2], [4, 2]]</span>, on the first iteration through the loop, <span class='m'>cx</span> will have the value <span class='m'>5</span> and <span class='m'>cy</span> will have the value <span class='m'>0</span>.</p>

<p>Line 73 determines which is larger: the absolute value of the difference of the X coordinates, or the absolute value of the difference of the Y coordinates. (<span class='m'>abs(cx - x) < abs(cy - y)</span> seems like much easier way to say that, doesn't it?). The <span class='m'>if-else</span> statement assigns the larger of the values to the <span class='m'>distance</span> variable.</p>

<p>So on each iteration of the <span class='m'>for</span> loop, <span class='m'>distance</span> is the distance of a treasure chest's distance from the sonar device. But we want the shortest (that is, smallest) distance of all the treasure chests. This is where the <span class='m'>smallestDistance</span> variable comes in. Whenever the <span class='m'>distance</span> variable is smaller than <span class='m'>smallestDistance</span>, then the value in <span class='m'>distance</span> becomes the new value of <span class='m'>smallestDistance</span>.</p>

<p>We give <span class='m'>smallestDistance</span> the impossibly high value of <span class='m'>chests</span> at the beginning of the loop so that at least one of the treasure chests we find will be put into <span class='m'>smallestDistance</span>. By the time the <span class='m'>chests</span> loop has finished, we know that <span class='m'>smallestDistance</span> holds the shortest distance between the sonar device and all of the treasure chests in the game.</p>

<blockquote class="sourcecode">
<ol start=81>
<li>&nbsp;&nbsp;&nbsp;&nbsp;if smallestDistance == 0:</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# xy is directly on a treasure chest!</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;chests.remove([x, y])</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return 'You have found a sunken treasure chest!'</li>
</ol>
</blockquote>

<p>The only time that <span class='m'>smallestDistance</span> is equal to <span class='m'>0</span> is when the sonar device's XY coordinates are the same as a treasure chest's XY coordinates. This means the player has correctly guessed the location of a treasure chest. We should remove this chest's two-integer list from the <span class='m'>chests</span> data structure with the <span class='m'>remove</span> list method.</p>

<h2>The <span class='m'>remove()</span> List Method</h2>

<p>The <span class='m'>remove</span> list method will remove the first occurence of the value passed as a parameter from the list. For example, try typing the following into the interactive shell:</p>

<blockquote><span class='m'>x = [42, 5, 10, 42]<br/>
x.remove(10)<br/>
x</span></blockquote>

<p class='centeredImageP'><img src='images/9_rem1.png' class='centeredImage'></p>

<p>You can see that the <span class='m'>10</span> value has been removed from the <span class='m'>x</span> list.</p>

<p>The <span class='m'>remove()</span> method removes the first occurrence of the value you pass it, and only the first. For example, type the following into the shell:</p>

<blockquote><span class='m'>x = [42, 5, 42]<br/>
x.remove(42)<br/>
x</span></blockquote>

<p class='centeredImageP'><img src='images/9_rem2.png' class='centeredImage'></p>

<p>Notice that only the first <span class='m'>42</span> value was removed, but the second one is still there.</p>

<p>The <span class='m'>remove()</span> method will cause an error if you try to remove a value that is not in the list:</p>

<p class='centeredImageP'><img src='images/9_rem3.png' class='centeredImage'></p>

<p>After removing the found treasure chest from the <span class='m'>chests</span> list, we return the string <span class='m'>'You have found a sunken treasure chest!'</span> to tell the caller that the guess was correct. Remember that any changes made to the list in a function will exist outside the function as well.</p>

<blockquote class="sourcecode">
<ol start=85>
<li>&nbsp;&nbsp;&nbsp;&nbsp;else:</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if smallestDistance < 10:</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;board[x][y] = str(smallestDistance)</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return 'Treasure detected at a distance of %s from the sonar device.' % (smallestDistance)</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else:</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;board[x][y] = 'O'</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return 'Sonar did not detect anything. All treasure chests out of range.'</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </li>
</ol>
</blockquote>

<p>The <span class='m'>else</span> block executes if <span class='m'>smallestDistance</span> was not <span class='m'>0</span>, which means the player did not guess an exact location of a treasure chest. We return two different strings, depending on if the sonar device was placed within range of any of the treasure chests. If it was, we mark the board with the string version of <span class='m'>smallestDistance</span>. If not, we mark the board with a <span class='m'>'0'</span>. 

<blockquote class="sourcecode">
<ol start=94>
<li>def enterPlayerMove():</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;# Let the player type in their move. Return a two-item list of int xy coordinates.</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;print 'Where do you want to drop the next sonar device? (0-59 0-14) (or type quit)'</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;while True:</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;move = raw_input()</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if move.lower() == 'quit':</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print 'Thanks for playing!'</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sys.exit()</li>
</ol>
</blockquote>

<p>This function collects the XY coordinates of the player's next move. It has a <span class='m'>while</span> loop so that it will keep asking the player for their next move. The player can also type in <span class='m'>chests</span> in order to quit the game. In that case, we call the <span class='m'>sys.exit()</span> function which immediately terminates the program.</p>

<blockquote class="sourcecode">
<ol start=103>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;move = move.split()</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if len(move) == 2 and move[0].isdigit() and move[1].isdigit() and isValidMove(int(move[0]), int(move[1])):</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return [int(move[0]), int(move[1])]</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print 'Enter a number from 0 to 59, a space, then a number from 0 to 14.'</li>
</ol>
</blockquote>

<p>Assuming the player has not typed in <span class='m'>'quit'</span>, we call the <span class='m'>split()</span> method on <span class='m'>move</span> and set the list it returns as the new value of <span class='m'>move</span>. What we expect <span class='m'>move</span> to be is a list of two numbers. These numbers will be strings, because the <span class='m'>chests</span> method returns a list of strings. But we can convert these to integers with the <span class='m'>int()</span> function.</p>

<p>If the player typed in something like <span class='m'>'1 2 3'</span>, then the list returned by <span class='m'>split()</span> would be <span class='m'>['1', '2', '3']</span>. In that case, the expression <span class='m'>len(move) == 2</span> would be <span class='m'>False</span> and the entire expression immediately evaluates to <span class='m'>False</span> (because of expression short-circuiting.)</p>

<p>If the list returned by <span class='m'>split()</span> does have a length of <span class='m'>2</span>, then it will have a <span class='m'>move[0]</span> and <span class='m'>move[1]</span>. We call the string method <span class='m'>isdigit()</span> on those strings. <span class='m'>isdigit()</span> will return <span class='m'>True</span> if the string consists solely of numbers. Otherwise it returns <span class='m'>False</span>. Try typing the following into the interactive shell:</p>

<blockquote class='sourceblurb'>
'42'.isdigit()<br/>
'forty'.isdigit()<br/>
''.isdigit()<br/>
'hello'.isdigit()<br/>
x = '10'<br/>
x.isdigit()<br/>
</blockquote>

<p class='centeredImageP'><img src='images/9_isdigit.png' class='centeredImage'></p>

<p>As you can see, both <span class='m'>move[0].isdigit()</span> and <span class='m'>move[1].isdigit()</span> must be <span class='m'>True</span>. The final part of this expression calls our <span class='m'>move[1]</span> function to check if the XY coordinates exist on the board. If all these expressions are <span class='m'>True</span>, then this function returns a two-integer list of the XY coordinates. Otherwise, the player will be asked to enter coordinates again.</p>

<blockquote class="sourcecode">
<ol start=109>
<li>def playAgain():</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;# This function returns True if the player wants to play again, otherwise it returns False.</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;print 'Do you want to play again? (yes or no)'</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;return raw_input().lower().startswith('y')</li>
</ol>
</blockquote>

<p>The <span class='m'>playAgain()</span> function will ask the player if they want to play again, and will keep asking until the player types in a string that begins with <span class='m'>'y'</span>. This function returns a boolean value.</p>

<blockquote class="sourcecode">
<ol start=115>
<li>def showInstructions():</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;print '''Instructions:</li>
<li>You are the captain of the Simon, a treasure-hunting ship. Your current mission</li>
<li>is to find the three sunken treasure chests that are lurking in the part of the</li>
<li>ocean you are in and collect them.</li>
<li></li>
<li>To play, enter the coordinates of the point in the ocean you wish to drop a</li>
<li>sonar device. The sonar can find out how far away the closest chest is to it.</li>
<li>For example, the d below marks where the device was dropped, and the 2's</li>
<li>represent distances of 2 away from the device. The 4's represent</li>
<li>distances of 4 away from the device.</li>
<li></li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;444444444</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;4 22222 4</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;4 2&nbsp;&nbsp;&nbsp;2 4</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;4 2 d 2 4</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;4 2&nbsp;&nbsp;&nbsp;2 4</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;4 22222 4</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;444444444</li>
<li>Press enter to continue...'''</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;raw_input()</li>
</ol>
</blockquote>

<p>The <span class='m'>showInstructions()</span> is just a couple of <span class='m'>print</span> statements that print mutli-line strings. The <span class='m'>raw_input()</span> function just gives the player a chance to press Enter before printing the next string. This is because the screen can only show 25 lines of text at a time.</p>

<blockquote class="sourcecode">
<ol start=139>
<li>&nbsp;&nbsp;&nbsp;&nbsp;print '''For example, here is a treasure chest (the c) located a distance of 2 away</li>
<li>from the sonar device (the d):</li>
<li></li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;22222</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;c&nbsp;&nbsp;&nbsp;2</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;2 d 2</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;2</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;22222</li>
<li></li>
<li>The point where the device was dropped will be marked with a 2.</li>
<li></li>
<li>The treasure chests don't move around. Sonar devices can detect treasure</li>
<li>chests up to a distance of 9. If all chests are out of range, the point</li>
<li>will be marked with O</li>
<li></li>
<li>If a device is directly dropped on a treasure chest, you have discovered </li>
<li>the location of the chest, and it will be collected. The sonar device will</li>
<li>remain there.</li>
<li></li>
<li>When you collect a chest, all sonar devices will update to locate the next</li>
<li>closest sunken treasure chest.</li>
<li>Press enter to continue...'''</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;raw_input()</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;print</li>
<li></li>
</ol>
</blockquote>

<p>This is the rest of the instructions in one multi-line string. After the player presses Enter, the function returns.</p>

<p>That is all of the functions we will define for our game. The rest of the program is the main part of our game.</p>

<blockquote class="sourcecode">
<ol start=165>
<li>print 'S O N A R !'</li>
<li>print</li>
<li>print 'Would you like to view the instructions? (yes/no)'</li>
<li>if raw_input().lower().startswith('y'):</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;showInstructions()</li>
</ol>
</blockquote>

<p>The expression <span class='m'>raw_input().lower().startswith('y')</span> asks the player if they want to see the instructions, and evaluates to <span class='m'>True</span> if the player typed in a string that began with <span class='m'>'y'</span> or <span class='m'>'Y'</span>. If so, <span class='m'>showInstructions()</span> is called.</p>

<blockquote class="sourcecode">
<ol start=171>
<li>while True:</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;# game setup</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;sonarDevices = 16</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;theBoard = getNewBoard()</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;theChests = getRandomChests(3)</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;drawBoard(theBoard)</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;previousMoves = []</li>
</ol>
</blockquote>

<p>This <span class='m'>while</span> loop is the main game loop. Here are what the variables are for:</p>

<blockquote>
<table border='0'>
<tr><td><span class='m'>sonarDevices</span></td><td>The number of sonar devices (and turns) the player has left.</td></tr>
<tr><td><span class='m'>theBoard</span></td><td>The board data structure we will use for this game. <span class='m'>getNewBoard()</span> will set us up with a fresh board.</td></tr>
<tr><td><span class='m'>theChests</span></td><td>The list of chest data structures. <span class='m'>getRandomChests()</span> will return a list of three treasure chests at random places on the board.</td></tr>
<tr><td><span class='m'>previousMoves</span></td><td>A list of all the XY moves that the player has made in the game.</td></tr>
</table>
</blockquote>

<blockquote class="sourcecode">
<ol start=179>
<li>&nbsp;&nbsp;&nbsp;&nbsp;while sonarDevices > 0:</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# Start of a turn:</li>
<li></li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# sonar device/chest status</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if sonarDevices > 1: extraSsonar = 's'</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else: extraSsonar = ''</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if len(theChests) > 1: extraSchest = 's'</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else: extraSchest = ''</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print 'You have %s sonar device%s left. %s treasure chest%s remaining.' % (sonarDevices, extraSsonar, len(theChests), extraSchest)</li>
</ol>
</blockquote>

<p>This <span class='m'>while</span> loop executes as long as the player has sonar devices remaining. We want to print a message telling the user how many sonar devices and treasure chests are left. But there is a problem. If there are two or more sonar devices left, we want to print <span class='m'>'2 sonar devices'</span>. But if there is only one sonar device left, we want to print <span class='m'>'1 sonar device'</span> left. We only want the plural form of devices if there are multiple sonar devices. The same goes for <span class='m'>'2 treasure chests'</span> and <span class='m'>'1 treasure chest'</span>.</p>

<p>So we have two string variables named <span class='m'>while</span> and <span class='m'>while</span>, which contain a <span class='m'>while</span> if there are multiple sonar devices or treasures chests. Otherwise, they are blank. We use them in the <span class='m'>while</span> statement on line 187.</p>

<blockquote class="sourcecode">
<ol start=189>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;x, y = enterPlayerMove()</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;previousMoves.append([x, y]) # we must track all moves so that sonar devices can be updated.</li>
<li></li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;moveResult = makeMove(theBoard, theChests, x, y)</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if moveResult == False:</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;continue</li>
</ol>
</blockquote>

<p>Line 189 uses the multiple assignment trick. <span class='m'>enterPlayerMove()</span> returns a two-item list. The first item will be stored in the <span class='m'>x</span> variable and the second will be stored in the <span class='m'>y</span> variable. We then put these two variables into another two-item list, which we store in the <span class='m'>previousMoves</span> list with the <span class='m'>append()</span> method. This means <span class='m'>previousMoves</span> is a list of XY coordinates of each move the player makes in this game.</p>

<p>The <span class='m'>x</span> and <span class='m'>y</span> variables, along with <span class='m'>theBoard</span> and <span class='m'>theChests</span> (which represent the current state of the game board) are all sent to the <span class='m'>makeMove()</span> function. As we have already seen, this function will make the necessary modifications to the game board. If <span class='m'>makeMove()</span> returns the value <span class='m'>False</span>, then there was a problem with the <span class='m'>x</span> and <span class='m'>y</span> values we passed it. The <span class='m'>while</span> statement will go back to the start of the <span class='m'>while</span> loop that began on line 179 to ask the player for XY coordinates again.</p>

<blockquote class="sourcecode">
<ol start=195>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else:</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if moveResult == 'You have found a sunken treasure chest!':</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# update all the sonar devices currently on the map.</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for x, y in previousMoves:</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;makeMove(theBoard, theChests, x, y)</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;drawBoard(theBoard)</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print moveResult</li>
</ol>
</blockquote>

<p>If <span class='m'>makeMove()</span> did not return the value <span class='m'>False</span>, it would have returned a string that tells us what were the results of that move. If this string was <span class='m'>while</span>, then that means we should update all the sonar devices on the board so they detect the second closest treasure chest on the board. We have the XY coordinates of all the sonar devices currently on the board stored in <span class='m'>previousMoves</span>. So we can just pass all of these XY coordinates to the <span class='m'>makeMove()</span> function again to have it redraw the values on the board.</p>

<p>We don't have to worry about this call to <span class='m'>makeMove()</span> having errors, because we already know all the XY coordinates in <span class='m'>previousMoves</span> are valid. We also know that this call to <span class='m'>makeMove()</span> won't find any new treasure chests, because they would have already been removed from the board when that move was first made.</p>

<p>The <span class='m'>for</span> loop on line 198 also uses the same multiple assignment trick for <span class='m'>x</span> and <span class='m'>y</span> because the items in <span class='m'>previousMoves</span> list are themselves two-item lists. Because we don't print anything here, the player doesn't realize we are redoing all of the previous moves. It just appears that the board has been entirely updated.</p>

<blockquote class="sourcecode">
<ol start=203>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if len(theChests) == 0:</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print 'You have found all the sunken treasure chests! Congratulations and good game!'</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break</li>
</ol>
</blockquote>

<p>Remember that the <span class='m'>makeMove()</span> function modifies the <span class='m'>theChests</span> list we send it. Because <span class='m'>theChests</span> is a list, any changes made to it inside the function will persist after execution returns from the function. <span class='m'>makeMove(0</span> removes items from <span class='m'>theChests</span> when treasure chests are found, so eventually (if the player guesses correctly) all of the treasure chests will have been removed. (Remember, by "treasure chest" we mean the two-item lists of the XY coordinates inside the <span class='m'>theChests</span> list.)</p>

<p>When all the treasure chests have been found on the board and removed from <span class='m'>theChests</span>, the <span class='m'>theChests</span> list will have a length of <span class='m'>0</span>. When that happens, we display a congratulations to the player, and then execute a <span class='m'>break</span> statement to break out of this <span class='m'>while</span> loop. Execution will then move down to line 209 (the first line after the <span class='m'>while</span> block.)</p>

<blockquote class="sourcecode">
<ol start=207>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sonarDevices -= 1</li>
</ol>
</blockquote>

<p>This is the last line of the <span class='m'>while</span> loop that started on line 179. We decrement the <span class='m'>sonarDevices</span> variable because the player has used one. If the player keeps missing the treasure chests, eventually <span class='m'>sonarDevices</span> will be reduced to <span class='m'>0</span>. After this line, execution jumps back up to line 179 so we can re-evaluate the <span class='m'>while</span> statement's condition (which is <span class='m'>sonarDevices > 0</span>). If <span class='m'>sonarDevices</span> is <span class='m'>0</span>, then the condition will be <span class='m'>False</span> and execution will continue outside the <span class='m'>while</span> block on line 209.</p>

<p>But until then, the condition will remain <span class='m'>while</span> and the player can keep making guesses.</p>

<blockquote class="sourcecode">
<ol start=209>
<li>&nbsp;&nbsp;&nbsp;&nbsp;if sonarDevices == 0:</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print 'We\'ve run out of sonar devices! Now we have to turn the ship around and head'</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print 'for home with treasure chests still out there! Game over.'</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print '&nbsp;&nbsp;&nbsp;&nbsp;The remaining chests were here:'</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for x, y in theChests:</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print '&nbsp;&nbsp;&nbsp;&nbsp;%s, %s' % (x, y)</li>
</ol>
</blockquote>

<p>Line 209 is the first line outside the <span class='m'>while</span> loop. By this point the game is over. But how do we tell if the player won or not? The only two places where the program execution would have left the <span class='m'>while</span> loop is on line 179 if the condition failed. In that case, <span class='m'>while</span> would be <span class='m'>while</span> and the player would have lost.</p>

<p>The second place is the <span class='m'>break</span> statement on line 205. That statement is executed if the player has found all the treasure chests before running out of sonar devices. In that case, <span class='m'>sonarDevices</span> would be some value greater than <span class='m'>0</span>.</p>

<p>We've already printed a congratulations if the player won, so let's just check if the player lost and display a message telling them so. We will also set up a <span class='m'>for</span> loop that will go through the treasure chests remaining in <span class='m'>theChests</span> and show them to the player.</p>

<blockquote class="sourcecode">
<ol start=216>
<li>&nbsp;&nbsp;&nbsp;&nbsp;if not playAgain():</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sys.exit()</li>
</ol>
</blockquote>

<p>Win or lose, we call the <span class='m'>playAgain()</span> function to let the player type in whether they want to keep playing or not. If not, then <span class='m'>playAgain()</span> returns <span class='m'>False</span>. The <span class='m'>not</span> operator changes this to <span class='m'>True</span>, making the <span class='m'>if</span> statement's condition <span class='m'>True</span> and the <span class='m'>sys.exit()</span> function is executed. This will cause the program to terminate.</p>

<p>Otherwise, execution jumps back to the beginning of the <span class='m'>not</span> loop on line 171.</p>



<blockquote class='inthischapter'><h3>Things Covered In This Chapter:</h3>
<ul>
<li>Cartesian coordinate systems.</li>
<li>The X-axis and Y-axis.</li>
<li>Absolute values and the <span class='m'>abs()</span> function.</li>
<li>The <span class='m'>remove()</span> list method.</li>
<li>The <span class='m'>isdigit()</span> string method.</li>
</ul>
</blockquote>

</body>
</html>